package com.gitee.wsl.compose.modifier.input.gestures

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.calculateZoom
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import com.gitee.wsl.compose.modifier.ModifierTouchScope

@Stable
fun Modifier.touchToScale(
    scaleRatio: Float = 0.9f,
    onClick: () -> Unit = {}
): Modifier = composed {
    val interactionSource = remember {
        MutableInteractionSource()
    }

    var isPressed by remember {
        mutableStateOf(false)
    }

    val realScaleRation by animateFloatAsState(
        if (isPressed) scaleRatio else 1f
    )

    LaunchedEffect(interactionSource) {
        interactionSource.interactions.collect { interaction ->
            when (interaction) {
                is PressInteraction.Press   -> isPressed = true
                is PressInteraction.Release -> isPressed = false
                is PressInteraction.Cancel  -> isPressed = false
            }
        }
    }
    this.then(Modifier.clickable(interactionSource = interactionSource, indication = null, onClick = onClick).graphicsLayer {
        scaleX = realScaleRation
        scaleY = realScaleRation
        transformOrigin = TransformOrigin.Center
    })
}

fun ModifierTouchScope.touchToScale(
    scaleRatio: Float = 0.9f,
    onClick: () -> Unit = {}
){
    modifier = modifier.touchToScale(scaleRatio, onClick)
}

/**
 * @param onFingerCountChange 屏幕手指数变化 原本是打算在缩放时屏蔽掉列表滚动和点击事件的
 * @param onScale 缩放
 */
fun Modifier.onScaleEvent(
    onFingerCountChange: ((Int) -> Unit)? = null,
    onScale: (Float) -> Unit
): Modifier = composed {
    var fingerCount by rememberSaveable { mutableIntStateOf(0) }

    pointerInput(Unit) {
        awaitEachGesture {
            do {
                val event = awaitPointerEvent()
                if (event.changes.size != fingerCount) {
                    fingerCount = event.changes.size
                    onFingerCountChange?.invoke(fingerCount)
                }
                if (event.changes.size >= 2) {
                    val z = event.calculateZoom()
                    if (z != 1f) {
                        onScale(z)
                        event.changes.forEach { it.consume() }
                    }
                }
            } while (event.changes.any { it.pressed })
            fingerCount = 0
            onFingerCountChange?.invoke(fingerCount)
        }
    }
}